#include "cross_process_bag.h"
#include "base64.h"
#include "helper.h"
#include <regex>
#include <iostream>
#include <utility>
#include <vector>
#include <malloc.h>

CrossProcessBag::CrossProcessBag(std::string serviceId,
                                 std::string serviceInstanceId,
                                 std::string segmentId,
                                 int version,
                                 const std::string &header) : version(version),
                                                              currentTraceId(std::move(segmentId)),
                                                              currentServiceId(std::move(serviceId)),
                                                              currentServiceInstance(std::move(serviceInstanceId))
{
    sample = 0;
    parentSpanId = 0;
    decode(header);
}

void CrossProcessBag::decode(const std::string &h)
{

    std::regex ws_re;
    switch (version)
    {
    case VERSION_8:
        ws_re = "-";
        break;
    }

    std::vector<std::string> header_bag = split(h, "-");

    if (header_bag.size() >= 8)
    {
        sample = std::stoi(header_bag[0]);
        traceId = Base64::decode(header_bag[1]);
        parentSegmentId = Base64::decode(header_bag[2]);
        parentSpanId = std::stoi(header_bag[3]);
        parentService = Base64::decode(header_bag[4]);
        parentServiceInstance = Base64::decode(header_bag[5]);
        parentEndpoint = Base64::decode(header_bag[6]);
        networkAddressUsedAtPeer = Base64::decode(header_bag[7]);
    }
    else
    {
        traceId = currentTraceId;
    }

    header_bag.clear();
    std::vector<std::string>().swap(header_bag);
    malloc_trim(0);
}

std::string CrossProcessBag::encode(int spanId, const std::string &peer)
{

    std::vector<std::string> tmp;
    tmp.emplace_back("1");
    tmp.emplace_back(Base64::encode(traceId));
    tmp.emplace_back(Base64::encode(currentTraceId));
    tmp.emplace_back(std::to_string(spanId));
    tmp.emplace_back(Base64::encode(currentServiceId));
    tmp.emplace_back(Base64::encode(currentServiceInstance));
    tmp.emplace_back(Base64::encode(currentOperationName));
    tmp.emplace_back(Base64::encode(peer));

    std::string header;

    for (const auto &val : tmp)
    {
        header.append(val);
        header.append("-");
    }

    header.erase(header.end() - 1);
    //    std::cout << header << std::endl;

    return header;
}

void CrossProcessBag::setOperationName(std::string name)
{
    currentOperationName = std::move(name);
}

std::string CrossProcessBag::getTraceId()
{
    return traceId;
}

std::string CrossProcessBag::getParentTraceSegmentId()
{
    return parentSegmentId;
}

int CrossProcessBag::getParentSpanId() const
{
    return parentSpanId;
}

std::string CrossProcessBag::getParentService()
{
    return parentService;
}

std::string CrossProcessBag::getParentServiceInstance()
{
    return parentServiceInstance;
}

std::string CrossProcessBag::getParentEndpoint()
{
    return parentEndpoint;
}

std::string CrossProcessBag::getNetworkAddressUsedAtPeer()
{
    return networkAddressUsedAtPeer;
}